home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Unix / Shells / tcsh / Source / sh.exp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-21  |  17.2 KB  |  888 lines

  1. /* $Header: /u/christos/src/tcsh-6.03/RCS/sh.exp.c,v 3.16 1992/11/14 20:40:02 christos Exp $ */
  2. /*
  3.  * sh.exp.c: Expression evaluations
  4.  */
  5. /*-
  6.  * Copyright (c) 1980, 1991 The Regents of the University of California.
  7.  * All rights reserved.
  8.  *
  9.  * Redistribution and use in source and binary forms, with or without
  10.  * modification, are permitted provided that the following conditions
  11.  * are met:
  12.  * 1. Redistributions of source code must retain the above copyright
  13.  *    notice, this list of conditions and the following disclaimer.
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in the
  16.  *    documentation and/or other materials provided with the distribution.
  17.  * 3. All advertising materials mentioning features or use of this software
  18.  *    must display the following acknowledgement:
  19.  *    This product includes software developed by the University of
  20.  *    California, Berkeley and its contributors.
  21.  * 4. Neither the name of the University nor the names of its contributors
  22.  *    may be used to endorse or promote products derived from this software
  23.  *    without specific prior written permission.
  24.  *
  25.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  26.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  29.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  31.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  34.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35.  * SUCH DAMAGE.
  36.  */
  37. #include "sh.h"
  38.  
  39. RCSID("$Id: sh.exp.c,v 3.16 1992/11/14 20:40:02 christos Exp $")
  40.  
  41. /*
  42.  * C shell
  43.  */
  44.  
  45. #define IGNORE    1    /* in ignore, it means to ignore value, just parse */
  46. #define NOGLOB    2    /* in ignore, it means not to globone */
  47.  
  48. #define    ADDOP    1
  49. #define    MULOP    2
  50. #define    EQOP    4
  51. #define    RELOP    8
  52. #define    RESTOP    16
  53. #define    ANYOP    31
  54.  
  55. #define    EQEQ    1
  56. #define    GTR    2
  57. #define    LSS    4
  58. #define    NOTEQ    6
  59. #define EQMATCH 7
  60. #define NOTEQMATCH 8
  61.  
  62. static    int     sh_access    __P((Char *, int));
  63. static    int     exp1        __P((Char ***, bool));
  64. static    int     exp2        __P((Char ***, bool));
  65. static    int     exp2a        __P((Char ***, bool));
  66. static    int     exp2b        __P((Char ***, bool));
  67. static    int     exp2c        __P((Char ***, bool));
  68. static    Char     *exp3        __P((Char ***, bool));
  69. static    Char     *exp3a        __P((Char ***, bool));
  70. static    Char     *exp4        __P((Char ***, bool));
  71. static    Char     *exp5        __P((Char ***, bool));
  72. static    Char     *exp6        __P((Char ***, bool));
  73. static    void     evalav        __P((Char **));
  74. static    int     isa        __P((Char *, int));
  75. static    int     egetn        __P((Char *));
  76.  
  77. #ifdef EDEBUG
  78. static    void     etracc        __P((char *, Char *, Char ***));
  79. static    void     etraci        __P((char *, int, Char ***));
  80. #endif
  81.  
  82.  
  83. /*
  84.  * shell access function according to POSIX and non POSIX
  85.  * From Beto Appleton (beto@aixwiz.aix.ibm.com)
  86.  */
  87. static int
  88. sh_access(fname, mode)
  89.     Char *fname;
  90.     int mode;
  91. {
  92. #ifdef POSIX
  93.     struct stat     statb;
  94. #endif /* POSIX */
  95.     char *name = short2str(fname);
  96.  
  97.     if (*name == '\0')
  98.     return 1;
  99.  
  100. #ifndef POSIX
  101.     return access(name, mode);
  102. #else /* POSIX */
  103.  
  104.     /*
  105.      * POSIX 1003.2-d11.2 
  106.      *    -r file        True if file exists and is readable. 
  107.      *    -w file        True if file exists and is writable. 
  108.      *            True shall indicate only that the write flag is on. 
  109.      *            The file shall not be writable on a read-only file
  110.      *            system even if this test indicates true.
  111.      *    -x file        True if file exists and is executable. 
  112.      *            True shall indicate only that the execute flag is on. 
  113.      *            If file is a directory, true indicates that the file 
  114.      *            can be searched.
  115.      */
  116.     if (mode != W_OK && mode != X_OK)
  117.     return access(name, mode);
  118.  
  119.     if (stat(name, &statb) == -1) 
  120.     return 1;
  121.  
  122.     if (access(name, mode) == 0) {
  123. #ifdef S_ISDIR
  124.     if (S_ISDIR(statb.st_mode) && mode == X_OK)
  125.         return 0;
  126. #endif /* S_ISDIR */
  127.  
  128.     /* root needs permission for someone */
  129.     switch (mode) {
  130.     case W_OK:
  131.         mode = S_IWUSR | S_IWGRP | S_IWOTH;
  132.         break;
  133.     case X_OK:
  134.         mode = S_IXUSR | S_IXGRP | S_IXOTH;
  135.         break;
  136.     default:
  137.         abort();
  138.         break;
  139.     }
  140.  
  141.     } 
  142.  
  143.     else if (euid == statb.st_uid)
  144.     mode <<= 6;
  145.  
  146.     else if (egid == statb.st_gid)
  147.     mode <<= 3;
  148.  
  149. # ifdef NGROUPS_MAX
  150.     else {
  151. #  if defined(__386BSD__) || defined(BSD4_4)
  152.     /*
  153.      * These two decided that setgroup() should take an array of int's
  154.      * and they define _SC_NGROUPS_MAX without having sysconf
  155.      */
  156. #   undef _SC_NGROUPS_MAX    
  157. #   define GID_T int
  158. #  else
  159. #   define GID_T gid_t
  160. #  endif /* __386BSD__ || BSD4_4 */
  161.     /* you can be in several groups */
  162.     int    n;
  163.     GID_T    *groups;
  164.  
  165.     /*
  166.      * Try these things to find a positive maximum groups value:
  167.      *   1) sysconf(_SC_NGROUPS_MAX)
  168.      *   2) NGROUPS_MAX
  169.      *   3) getgroups(0, unused)
  170.      * Then allocate and scan the groups array if one of these worked.
  171.      */
  172. #  ifdef _SC_NGROUPS_MAX
  173.     if ((n = sysconf(_SC_NGROUPS_MAX)) == -1)
  174. #  endif /* _SC_NGROUPS_MAX */
  175.         n = NGROUPS_MAX;
  176.     if (n <= 0)
  177.         n = getgroups(0, (GID_T *) NULL);
  178.  
  179.     if (n > 0) {
  180.         groups = (GID_T *) xmalloc((size_t) (n * sizeof(GID_T)));
  181.         n = getgroups(n, groups);
  182.         while (--n >= 0)
  183.         if (groups[n] == statb.st_gid) {
  184.             mode <<= 3;
  185.             break;
  186.         }
  187.     }
  188.     }
  189. # endif /* NGROUPS_MAX */
  190.  
  191.     if (statb.st_mode & mode)
  192.     return 0;
  193.     else
  194.     return 1;
  195. #endif /* !POSIX */
  196. }
  197.  
  198. int
  199. expr(vp)
  200.     register Char ***vp;
  201. {
  202.     return (exp0(vp, 0));
  203. }
  204.  
  205. int
  206. exp0(vp, ignore)
  207.     register Char ***vp;
  208.     bool    ignore;
  209. {
  210.     register int p1 = exp1(vp, ignore);
  211.  
  212. #ifdef EDEBUG
  213.     etraci("exp0 p1", p1, vp);
  214. #endif
  215.     if (**vp && eq(**vp, STRor2)) {
  216.     register int p2;
  217.  
  218.     (*vp)++;
  219.     p2 = exp0(vp, (ignore & IGNORE) || p1);
  220. #ifdef EDEBUG
  221.     etraci("exp0 p2", p2, vp);
  222. #endif
  223.     return (p1 || p2);
  224.     }
  225.     return (p1);
  226. }
  227.  
  228. static int
  229. exp1(vp, ignore)
  230.     register Char ***vp;
  231.     bool    ignore;
  232. {
  233.     register int p1 = exp2(vp, ignore);
  234.  
  235. #ifdef EDEBUG
  236.     etraci("exp1 p1", p1, vp);
  237. #endif
  238.     if (**vp && eq(**vp, STRand2)) {
  239.     register int p2;
  240.  
  241.     (*vp)++;
  242.     p2 = exp1(vp, (ignore & IGNORE) || !p1);
  243. #ifdef EDEBUG
  244.     etraci("exp1 p2", p2, vp);
  245. #endif
  246.     return (p1 && p2);
  247.     }
  248.     return (p1);
  249. }
  250.  
  251. static int
  252. exp2(vp, ignore)
  253.     register Char ***vp;
  254.     bool    ignore;
  255. {
  256.     register int p1 = exp2a(vp, ignore);
  257.  
  258. #ifdef EDEBUG
  259.     etraci("exp3 p1", p1, vp);
  260. #endif
  261.     if (**vp && eq(**vp, STRor)) {
  262.     register int p2;
  263.  
  264.     (*vp)++;
  265.     p2 = exp2(vp, ignore);
  266. #ifdef EDEBUG
  267.     etraci("exp3 p2", p2, vp);
  268. #endif
  269.     return (p1 | p2);
  270.     }
  271.     return (p1);
  272. }
  273.  
  274. static int
  275. exp2a(vp, ignore)
  276.     register Char ***vp;
  277.     bool    ignore;
  278. {
  279.     register int p1 = exp2b(vp, ignore);
  280.  
  281. #ifdef EDEBUG
  282.     etraci("exp2a p1", p1, vp);
  283. #endif
  284.     if (**vp && eq(**vp, STRcaret)) {
  285.     register int p2;
  286.  
  287.     (*vp)++;
  288.     p2 = exp2a(vp, ignore);
  289. #ifdef EDEBUG
  290.     etraci("exp2a p2", p2, vp);
  291. #endif
  292.     return (p1 ^ p2);
  293.     }
  294.     return (p1);
  295. }
  296.  
  297. static int
  298. exp2b(vp, ignore)
  299.     register Char ***vp;
  300.     bool    ignore;
  301. {
  302.     register int p1 = exp2c(vp, ignore);
  303.  
  304. #ifdef EDEBUG
  305.     etraci("exp2b p1", p1, vp);
  306. #endif
  307.     if (**vp && eq(**vp, STRand)) {
  308.     register int p2;
  309.  
  310.     (*vp)++;
  311.     p2 = exp2b(vp, ignore);
  312. #ifdef EDEBUG
  313.     etraci("exp2b p2", p2, vp);
  314. #endif
  315.     return (p1 & p2);
  316.     }
  317.     return (p1);
  318. }
  319.  
  320. static int
  321. exp2c(vp, ignore)
  322.     register Char ***vp;
  323.     bool    ignore;
  324. {
  325.     register Char *p1 = exp3(vp, ignore);
  326.     register Char *p2;
  327.     register int i;
  328.  
  329. #ifdef EDEBUG
  330.     etracc("exp2c p1", p1, vp);
  331. #endif
  332.     if ((i = isa(**vp, EQOP)) != 0) {
  333.     (*vp)++;
  334.     if (i == EQMATCH || i == NOTEQMATCH)
  335.         ignore |= NOGLOB;
  336.     p2 = exp3(vp, ignore);
  337. #ifdef EDEBUG
  338.     etracc("exp2c p2", p2, vp);
  339. #endif
  340.     if (!(ignore & IGNORE))
  341.         switch (i) {
  342.  
  343.         case EQEQ:
  344.         i = eq(p1, p2);
  345.         break;
  346.  
  347.         case NOTEQ:
  348.         i = !eq(p1, p2);
  349.         break;
  350.  
  351.         case EQMATCH:
  352.         i = Gmatch(p1, p2);
  353.         break;
  354.  
  355.         case NOTEQMATCH:
  356.         i = !Gmatch(p1, p2);
  357.         break;
  358.         }
  359.     xfree((ptr_t) p1);
  360.     xfree((ptr_t) p2);
  361.     return (i);
  362.     }
  363.     i = egetn(p1);
  364.     xfree((ptr_t) p1);
  365.     return (i);
  366. }
  367.  
  368. static Char *
  369. exp3(vp, ignore)
  370.     register Char ***vp;
  371.     bool    ignore;
  372. {
  373.     register Char *p1, *p2;
  374.     register int i;
  375.  
  376.     p1 = exp3a(vp, ignore);
  377. #ifdef EDEBUG
  378.     etracc("exp3 p1", p1, vp);
  379. #endif
  380.     if ((i = isa(**vp, RELOP)) != 0) {
  381.     (*vp)++;
  382.     if (**vp && eq(**vp, STRequal))
  383.         i |= 1, (*vp)++;
  384.     p2 = exp3(vp, ignore);
  385. #ifdef EDEBUG
  386.     etracc("exp3 p2", p2, vp);
  387. #endif
  388.     if (!(ignore & IGNORE))
  389.         switch (i) {
  390.  
  391.         case GTR:
  392.         i = egetn(p1) > egetn(p2);
  393.         break;
  394.  
  395.         case GTR | 1:
  396.         i = egetn(p1) >= egetn(p2);
  397.         break;
  398.  
  399.         case LSS:
  400.         i = egetn(p1) < egetn(p2);
  401.         break;
  402.  
  403.         case LSS | 1:
  404.         i = egetn(p1) <= egetn(p2);
  405.         break;
  406.         }
  407.     xfree((ptr_t) p1);
  408.     xfree((ptr_t) p2);
  409.     return (putn(i));
  410.     }
  411.     return (p1);
  412. }
  413.  
  414. static Char *
  415. exp3a(vp, ignore)
  416.     register Char ***vp;
  417.     bool    ignore;
  418. {
  419.     register Char *p1, *p2, *op;
  420.     register int i;
  421.  
  422.     p1 = exp4(vp, ignore);
  423. #ifdef EDEBUG
  424.     etracc("exp3a p1", p1, vp);
  425. #endif
  426.     op = **vp;
  427.     if (op && any("<>", op[0]) && op[0] == op[1]) {
  428.     (*vp)++;
  429.     p2 = exp3a(vp, ignore);
  430. #ifdef EDEBUG
  431.     etracc("exp3a p2", p2, vp);
  432. #endif
  433.     if (op[0] == '<')
  434.         i = egetn(p1) << egetn(p2);
  435.     else
  436.         i = egetn(p1) >> egetn(p2);
  437.     xfree((ptr_t) p1);
  438.     xfree((ptr_t) p2);
  439.     return (putn(i));
  440.     }
  441.     return (p1);
  442. }
  443.  
  444. static Char *
  445. exp4(vp, ignore)
  446.     register Char ***vp;
  447.     bool    ignore;
  448. {
  449.     register Char *p1, *p2;
  450.     register int i = 0;
  451.  
  452.     p1 = exp5(vp, ignore);
  453. #ifdef EDEBUG
  454.     etracc("exp4 p1", p1, vp);
  455. #endif
  456.     if (isa(**vp, ADDOP)) {
  457.     register Char *op = *(*vp)++;
  458.  
  459.     p2 = exp4(vp, ignore);
  460. #ifdef EDEBUG
  461.     etracc("exp4 p2", p2, vp);
  462. #endif
  463.     if (!(ignore & IGNORE))
  464.         switch (op[0]) {
  465.  
  466.         case '+':
  467.         i = egetn(p1) + egetn(p2);
  468.         break;
  469.  
  470.         case '-':
  471.         i = egetn(p1) - egetn(p2);
  472.         break;
  473.         }
  474.     xfree((ptr_t) p1);
  475.     xfree((ptr_t) p2);
  476.     return (putn(i));
  477.     }
  478.     return (p1);
  479. }
  480.  
  481. static Char *
  482. exp5(vp, ignore)
  483.     register Char ***vp;
  484.     bool    ignore;
  485. {
  486.     register Char *p1, *p2;
  487.     register int i = 0;
  488.  
  489.     p1 = exp6(vp, ignore);
  490. #ifdef EDEBUG
  491.     etracc("exp5 p1", p1, vp);
  492. #endif
  493.     if (isa(**vp, MULOP)) {
  494.     register Char *op = *(*vp)++;
  495.  
  496.     p2 = exp5(vp, ignore);
  497. #ifdef EDEBUG
  498.     etracc("exp5 p2", p2, vp);
  499. #endif
  500.     if (!(ignore & IGNORE))
  501.         switch (op[0]) {
  502.  
  503.         case '*':
  504.         i = egetn(p1) * egetn(p2);
  505.         break;
  506.  
  507.         case '/':
  508.         i = egetn(p2);
  509.         if (i == 0)
  510.             stderror(ERR_DIV0);
  511.         i = egetn(p1) / i;
  512.         break;
  513.  
  514.         case '%':
  515.         i = egetn(p2);
  516.         if (i == 0)
  517.             stderror(ERR_MOD0);
  518.         i = egetn(p1) % i;
  519.         break;
  520.         }
  521.     xfree((ptr_t) p1);
  522.     xfree((ptr_t) p2);
  523.     return (putn(i));
  524.     }
  525.     return (p1);
  526. }
  527.  
  528. static Char *
  529. exp6(vp, ignore)
  530.     register Char ***vp;
  531.     bool    ignore;
  532. {
  533.     int     ccode, i = 0;
  534.     register Char *cp, *dp, *ep;
  535.  
  536.     if (**vp == 0)
  537.     stderror(ERR_NAME | ERR_EXPRESSION);
  538.     if (eq(**vp, STRbang)) {
  539.     (*vp)++;
  540.     cp = exp6(vp, ignore);
  541. #ifdef EDEBUG
  542.     etracc("exp6 ! cp", cp, vp);
  543. #endif
  544.     i = egetn(cp);
  545.     xfree((ptr_t) cp);
  546.     return (putn(!i));
  547.     }
  548.     if (eq(**vp, STRtilde)) {
  549.     (*vp)++;
  550.     cp = exp6(vp, ignore);
  551. #ifdef EDEBUG
  552.     etracc("exp6 ~ cp", cp, vp);
  553. #endif
  554.     i = egetn(cp);
  555.     xfree((ptr_t) cp);
  556.     return (putn(~i));
  557.     }
  558.     if (eq(**vp, STRLparen)) {
  559.     (*vp)++;
  560.     ccode = exp0(vp, ignore);
  561. #ifdef EDEBUG
  562.     etraci("exp6 () ccode", ccode, vp);
  563. #endif
  564.     if (*vp == 0 || **vp == 0 || ***vp != ')')
  565.         stderror(ERR_NAME | ERR_EXPRESSION);
  566.     (*vp)++;
  567.     return (putn(ccode));
  568.     }
  569.     if (eq(**vp, STRLbrace)) {
  570.     register Char **v;
  571.     struct command faket;
  572.     Char   *fakecom[2];
  573.  
  574.     faket.t_dtyp = NODE_COMMAND;
  575.     faket.t_dflg = F_BACKQ;
  576.     faket.t_dcar = faket.t_dcdr = faket.t_dspr = NULL;
  577.     faket.t_dcom = fakecom;
  578.     fakecom[0] = STRfakecom;
  579.     fakecom[1] = NULL;
  580.     (*vp)++;
  581.     v = *vp;
  582.     for (;;) {
  583.         if (!**vp)
  584.         stderror(ERR_NAME | ERR_MISSING, '}');
  585.         if (eq(*(*vp)++, STRRbrace))
  586.         break;
  587.     }
  588.     if (ignore & IGNORE)
  589.         return (Strsave(STRNULL));
  590.     psavejob();
  591.     if (pfork(&faket, -1) == 0) {
  592.         *--(*vp) = 0;
  593.         evalav(v);
  594.         exitstat();
  595.     }
  596.     pwait();
  597.     prestjob();
  598. #ifdef EDEBUG
  599.     etraci("exp6 {} status", egetn(value(STRstatus)), vp);
  600. #endif
  601.     return (putn(egetn(value(STRstatus)) == 0));
  602.     }
  603.     if (isa(**vp, ANYOP))
  604.     return (Strsave(STRNULL));
  605.     cp = *(*vp)++;
  606. #define FILETESTS "erwxfdzoplstX"
  607.     if (*cp == '-' && any(FILETESTS, cp[1])) {
  608.     struct stat stb;
  609.     Char *ft;
  610.  
  611.     for (ft = &cp[2]; *ft; ft++) 
  612.         if (!any(FILETESTS, *ft))
  613.         stderror(ERR_NAME | ERR_FILEINQ);
  614.     /*
  615.      * Detect missing file names by checking for operator in the file name
  616.      * position.  However, if an operator name appears there, we must make
  617.      * sure that there's no file by that name (e.g., "/") before announcing
  618.      * an error.  Even this check isn't quite right, since it doesn't take
  619.      * globbing into account.
  620.      */
  621.     if (isa(**vp, ANYOP) && stat(short2str(**vp), &stb))
  622.         stderror(ERR_NAME | ERR_FILENAME);
  623.  
  624.     dp = *(*vp)++;
  625.     if (ignore & IGNORE)
  626.         return (Strsave(STRNULL));
  627.     ep = globone(dp, G_ERROR);
  628.     ft = &cp[1];
  629.     do 
  630.         switch (*ft) {
  631.  
  632.         case 'r':
  633.         i = !sh_access(ep, R_OK);
  634.         break;
  635.  
  636.         case 'w':
  637.         i = !sh_access(ep, W_OK);
  638.         break;
  639.  
  640.         case 'x':
  641.         i = !sh_access(ep, X_OK);
  642.         break;
  643.  
  644.         case 'X':    /* tcsh extension, name is an executable in the path
  645.              * or a tcsh builtin command 
  646.              */
  647.         i = find_cmd(ep, 0);
  648.         break;
  649.  
  650.         case 't':    /* SGI extension, true when file is a tty */
  651.         i = isatty(atoi(short2str(ep)));
  652.         break;
  653.  
  654.         default:
  655.         if (
  656. #ifdef S_IFLNK
  657.             *ft == 'l' ? lstat(short2str(ep), &stb) :
  658. #endif
  659.             stat(short2str(ep), &stb)) {
  660.             xfree((ptr_t) ep);
  661.             return (Strsave(STR0));
  662.         }
  663.         switch (*ft) {
  664.  
  665.         case 'f':
  666. #ifdef S_ISREG
  667.             i = S_ISREG(stb.st_mode);
  668. #else
  669.             i = 0;
  670. #endif
  671.             break;
  672.  
  673.         case 'd':
  674. #ifdef S_ISDIR
  675.             i = S_ISDIR(stb.st_mode);
  676. #else
  677.             i = 0;
  678. #endif
  679.             break;
  680.  
  681.         case 'p':
  682. #ifdef S_ISFIFO
  683.             i = S_ISFIFO(stb.st_mode);
  684. #else
  685.             i = 0;
  686. #endif
  687.             break;
  688.  
  689.         case 'l':
  690. #ifdef S_ISLNK
  691.             i = S_ISLNK(stb.st_mode);
  692. #else
  693.             i = 0;
  694. #endif
  695.             break;
  696.  
  697.         /* 
  698.          * ARGH!!! sgi defines (-s == ! -z) Why? Can you change it? 
  699.          * Here I am not going to be compatible; they should fix it!
  700.          */
  701.         case 's':
  702. # ifdef S_ISSOCK
  703.             i = S_ISSOCK(stb.st_mode);
  704. # else
  705.             i = 0;
  706. # endif
  707.             break;
  708.  
  709.         case 'b':
  710. #ifdef S_ISBLK
  711.             i = S_ISBLK(stb.st_mode);
  712. #else
  713.             i = 0;
  714. #endif
  715.             break;
  716.  
  717.         case 'c':
  718. #ifdef S_ISCHR
  719.             i = S_ISCHR(stb.st_mode);
  720. #else
  721.             i = 0;
  722. #endif
  723.             break;
  724.  
  725.         case 'u':
  726. #ifdef S_ISUID
  727.             i = (S_ISUID & stb.st_mode) != 0;
  728. #else
  729.             i = 0;
  730. #endif
  731.             break;
  732.  
  733.         case 'g':
  734. #ifdef S_ISGID
  735.             i = (S_ISGID & stb.st_mode) != 0;
  736. #else
  737.             i = 0;
  738. #endif
  739.             break;
  740.  
  741.         case 'k':
  742. #ifdef S_ISVTX
  743.             i = (S_ISVTX & stb.st_mode) != 0;
  744. #else
  745.             i = 0;
  746. #endif
  747.             break;
  748.  
  749.         case 'z':
  750.             i = stb.st_size == 0;
  751.             break;
  752.  
  753.         case 'e':
  754.             i = 1;
  755.             break;
  756.  
  757.         case 'o':
  758.             i = stb.st_uid == uid;
  759.             break;
  760.         }
  761.         }
  762.     while (*++ft && i);
  763. #ifdef EDEBUG
  764.     etraci("exp6 -? i", i, vp);
  765. #endif
  766.     xfree((ptr_t) ep);
  767.     return (putn(i));
  768.     }
  769. #ifdef EDEBUG
  770.     etracc("exp6 default", cp, vp);
  771. #endif
  772.     return (ignore & NOGLOB ? Strsave(cp) : globone(cp, G_ERROR));
  773. }
  774.  
  775. static void
  776. evalav(v)
  777.     register Char **v;
  778. {
  779.     struct wordent paraml1;
  780.     register struct wordent *hp = ¶ml1;
  781.     struct command *t;
  782.     register struct wordent *wdp = hp;
  783.  
  784.     set(STRstatus, Strsave(STR0));
  785.     hp->prev = hp->next = hp;
  786.     hp->word = STRNULL;
  787.     while (*v) {
  788.     register struct wordent *new =
  789.     (struct wordent *) xcalloc(1, sizeof *wdp);
  790.  
  791.     new->prev = wdp;
  792.     new->next = hp;
  793.     wdp->next = new;
  794.     wdp = new;
  795.     wdp->word = Strsave(*v++);
  796.     }
  797.     hp->prev = wdp;
  798.     alias(¶ml1);
  799.     t = syntax(paraml1.next, ¶ml1, 0);
  800.     if (seterr)
  801.     stderror(ERR_OLD);
  802.     execute(t, -1, NULL, NULL);
  803.     freelex(¶ml1), freesyn(t);
  804. }
  805.  
  806. static int
  807. isa(cp, what)
  808.     register Char *cp;
  809.     register int what;
  810. {
  811.     if (cp == 0)
  812.     return ((what & RESTOP) != 0);
  813.     if (cp[1] == 0) {
  814.     if (what & ADDOP && (*cp == '+' || *cp == '-'))
  815.         return (1);
  816.     if (what & MULOP && (*cp == '*' || *cp == '/' || *cp == '%'))
  817.         return (1);
  818.     if (what & RESTOP && (*cp == '(' || *cp == ')' || *cp == '!' ||
  819.                   *cp == '~' || *cp == '^' || *cp == '"'))
  820.         return (1);
  821.     }
  822.     else if (cp[2] == 0) {
  823.     if (what & RESTOP) {
  824.         if (cp[0] == '|' && cp[1] == '&')
  825.         return (1);
  826.         if (cp[0] == '<' && cp[1] == '<')
  827.         return (1);
  828.         if (cp[0] == '>' && cp[1] == '>')
  829.         return (1);
  830.     }
  831.     if (what & EQOP) {
  832.         if (cp[0] == '=') {
  833.         if (cp[1] == '=')
  834.             return (EQEQ);
  835.         if (cp[1] == '~')
  836.             return (EQMATCH);
  837.         }
  838.         else if (cp[0] == '!') {
  839.         if (cp[1] == '=')
  840.             return (NOTEQ);
  841.         if (cp[1] == '~')
  842.             return (NOTEQMATCH);
  843.         }
  844.     }
  845.     }
  846.     if (what & RELOP) {
  847.     if (*cp == '<')
  848.         return (LSS);
  849.     if (*cp == '>')
  850.         return (GTR);
  851.     }
  852.     return (0);
  853. }
  854.  
  855. static int
  856. egetn(cp)
  857.     register Char *cp;
  858. {
  859.     if (*cp && *cp != '-' && !Isdigit(*cp))
  860.     stderror(ERR_NAME | ERR_EXPRESSION);
  861.     return (getn(cp));
  862. }
  863.  
  864. /* Phew! */
  865.  
  866. #ifdef EDEBUG
  867. static void
  868. etraci(str, i, vp)
  869.     char   *str;
  870.     int     i;
  871.     Char ***vp;
  872. {
  873.     xprintf("%s=%d\t", str, i);
  874.     blkpr(*vp);
  875.     xputchar('\n');
  876. }
  877. static void
  878. etracc(str, cp, vp)
  879.     char   *str;
  880.     Char   *cp;
  881.     Char ***vp;
  882. {
  883.     xprintf("%s=%s\t", str, cp);
  884.     blkpr(*vp);
  885.     xputchar('\n');
  886. }
  887. #endif
  888.